import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Stack;

public class calculatorGUI {
    private JFrame frame;
    private JPanel mainPanel;
    private CardLayout cardLayout;
    private JPanel simplePanel;
    private JPanel complexPanel;
    private JTextField simpleTextField;
    private JTextField complexTextField;
    private JButton clearButton;
    private JButton memoryRecallButton;
    private JButton memoryClearButton;
    private Stack<Double> memory; // 用于存储计算结果的栈

    public calculatorGUI() {
        frame = new JFrame("Calculator");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 500);
        frame.setLayout(new BorderLayout());

        // 设置字体
        Font font = new Font("Arial", Font.BOLD, 20);

        cardLayout = new CardLayout();
        mainPanel = new JPanel(cardLayout);

        simplePanel = new JPanel();
        simplePanel.setLayout(new GridBagLayout()); // 使用 GridBagLayout 进行布局
        simplePanel.setBackground(Color.LIGHT_GRAY);
        complexPanel = new JPanel();
        complexPanel.setLayout(new BoxLayout(complexPanel, BoxLayout.Y_AXIS));
        complexPanel.setBackground(Color.LIGHT_GRAY);

        // 创建文本框
        simpleTextField = new JTextField();
        simpleTextField.setPreferredSize(new Dimension(300, 50));
        simpleTextField.setFont(font);
        simpleTextField.setBackground(Color.WHITE);
        complexTextField = new JTextField();
        complexTextField.setPreferredSize(new Dimension(300, 50));
        complexTextField.setFont(font);
        complexTextField.setBackground(Color.WHITE);

        clearButton = new JButton("Clear");
        clearButton.setFont(font);
        clearButton.setBackground(Color.ORANGE);

        // 初始化记忆栈
        memory = new Stack<>();

        // 添加组件到简单运算面板
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 4;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(10, 10, 10, 10); // 增加组件之间的间距
        simplePanel.add(simpleTextField, gbc);
        gbc.gridy = 1;
        gbc.gridwidth = 1;
        gbc.weightx = 1.0; // 设置权重，使按钮均匀分布
        gbc.fill = GridBagConstraints.BOTH; // 填充整个单元格
        simplePanel.add(createSimpleButtons(), gbc);

        gbc.gridx = 3;
        gbc.gridy = 1;
        gbc.anchor = GridBagConstraints.EAST; // 将清除按钮对齐到右侧
        gbc.weightx = 0.0; // 清除按钮不需要权重
        gbc.fill = GridBagConstraints.NONE; // 不填充单元格
        simplePanel.add(clearButton, gbc);

        // 添加内存操作按钮
        memoryRecallButton = new JButton("MR");
        memoryRecallButton.setFont(font);
        memoryRecallButton.setBackground(Color.PINK);
        memoryRecallButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                recallMemory();
            }
        });
        simplePanel.add(memoryRecallButton, gbc);

        memoryClearButton = new JButton("MC");
        memoryClearButton.setFont(font);
        memoryClearButton.setBackground(Color.PINK);
        memoryClearButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                clearMemory();
            }
        });
        simplePanel.add(memoryClearButton, gbc);

        // 添加组件到复杂运算面板
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 4;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(10, 10, 10, 10);
        // 将复杂运算文本框添加到复杂运算面板中
        complexPanel.add(complexTextField, gbc);
        // 设置网格布局的纵坐标为1
        gbc.gridy = 1;
        // 设置网格布局的宽度为1
        gbc.gridwidth = 1;
        // 设置水平方向的权重为1.0，使组件在水平方向上可以拉伸
        gbc.weightx = 1.0;
        // 设置组件在水平和垂直方向上都填充整个单元格
        gbc.fill = GridBagConstraints.BOTH;
        complexPanel.add(createComplexButtons(), gbc);
        gbc.gridx = 3;
        gbc.gridy = 1;
        gbc.anchor = GridBagConstraints.EAST;
        gbc.weightx = 0.0;
        gbc.fill = GridBagConstraints.NONE;
        complexPanel.add(clearButton, gbc);
        complexPanel.add(memoryRecallButton, gbc);
        complexPanel.add(memoryClearButton, gbc);

        mainPanel.add(simplePanel, "Simple");
        mainPanel.add(complexPanel, "Complex");

        frame.add(mainPanel, BorderLayout.CENTER);

        // 添加切换界面的按钮
        JButton switchButton = new JButton("Switch");
        switchButton.setFont(font);
        switchButton.setBackground(Color.GREEN);
        switchButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                cardLayout.next(mainPanel);
            }
        });
        frame.add(switchButton, BorderLayout.SOUTH);

        // 清除按钮的动作
        clearButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 获取当前显示的面板
                Component currentPanel = mainPanel
                        .getComponent(mainPanel.getComponentZOrder(mainPanel.getComponent(0)));
                // 根据当前面板清空相应的文本框
                if (currentPanel == simplePanel) {
                    simpleTextField.setText("");
                } else {
                    complexTextField.setText("");
                }
            }
        });

        // 键盘输入处理
        simpleTextField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int key = e.getKeyCode();
                if (key >= KeyEvent.VK_0 && key <= KeyEvent.VK_9) {
                    simpleTextField.setText(simpleTextField.getText() + (char) key);
                } else if (key == KeyEvent.VK_PLUS) {
                    // 如果按下的是加号键
                    if (key == KeyEvent.VK_PLUS) {
                        // 在简单运算文本框中添加加号
                        simpleTextField.setText(simpleTextField.getText() + "+");
                    }
                    // 如果按下的是减号键
                    else if (key == KeyEvent.VK_MINUS) {
                        // 在简单运算文本框中添加减号
                        simpleTextField.setText(simpleTextField.getText() + "-");
                    }
                    // 如果按下的是乘号键
                    else if (key == KeyEvent.VK_MULTIPLY) {
                        // 在简单运算文本框中添加乘号
                        simpleTextField.setText(simpleTextField.getText() + "*");
                    } else if (key == KeyEvent.VK_DIVIDE) {
                        simpleTextField.setText(simpleTextField.getText() + "/");
                    } else if (key == KeyEvent.VK_ENTER) {
                        calculateSimpleResult();
                    } else if (key == KeyEvent.VK_BACK_SPACE) {
                        String currentText = simpleTextField.getText();
                        if (currentText.length() > 0) {
                            simpleTextField.setText(currentText.substring(0, currentText.length() - 1));
                        }
                    } else if (key == KeyEvent.VK_LEFT_PARENTHESIS) {
                        simpleTextField.setText(simpleTextField.getText() + "(");
                    } else if (key == KeyEvent.VK_RIGHT_PARENTHESIS) {
                        simpleTextField.setText(simpleTextField.getText() + ")");
                    } else {
                        // 处理其他不合法的按键
                        simpleTextField.setText("Error: Invalid key");
                    }
                } else {
                    // 处理其他不合法的按键
                    simpleTextField.setText("Error: Invalid key");
                }
            }
        });

        complexTextField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int key = e.getKeyCode();
                // 如果按下的是数字键（0-9）
                if (key >= KeyEvent.VK_0 && key <= KeyEvent.VK_9) {
                    // 在复杂运算文本框中添加按下的数字
                    complexTextField.setText(complexTextField.getText() + (char) key);
                }
                // 如果按下的是加号键
                else if (key == KeyEvent.VK_PLUS) {
                    // 在复杂运算文本框中添加加号
                    complexTextField.setText(complexTextField.getText() + "+");
                }
                // 如果按下的是减号键
                else if (key == KeyEvent.VK_MINUS) {
                    // 在复杂运算文本框中添加减号
                    complexTextField.setText(complexTextField.getText() + "-");
                }
                // 如果按下的是乘号键
                else if (key == KeyEvent.VK_MULTIPLY) {
                    // 在复杂运算文本框中添加乘号
                    complexTextField.setText(complexTextField.getText() + "*");
                }
                // 如果按下的是除号键
                else if (key == KeyEvent.VK_DIVIDE) {
                    // 在复杂运算文本框中添加除号
                    complexTextField.setText(complexTextField.getText() + "/");
                }
                // 如果按下的是回车键
                else if (key == KeyEvent.VK_ENTER) {
                    // 调用 calculateComplexResult 方法计算复杂运算的结果
                    calculateComplexResult();
                }
                // 如果按下的是退格键
                else if (key == KeyEvent.VK_BACK_SPACE) {
                    // 获取复杂运算文本框中的当前文本
                    String currentText = complexTextField.getText();
                    // 如果当前文本长度大于0
                    if (currentText.length() > 0) {
                        // 删除最后一个字符
                        complexTextField.setText(currentText.substring(0, currentText.length() - 1));
                    }
                }
                // 如果按下的是左括号键
                else if (key == KeyEvent.VK_LEFT_PARENTHESIS) {
                    // 在复杂运算文本框中添加左括号
                    complexTextField.setText(complexTextField.getText() + "(");
                }
                // 如果按下的是右括号键
                else if (key == KeyEvent.VK_RIGHT_PARENTHESIS) {
                    // 在复杂运算文本框中添加右括号
                    complexTextField.setText(complexTextField.getText() + ")");
                }
                // 如果按下的是Shift+6键
                else if (key == KeyEvent.VK_6) {
                    // 如果Shift键被按下
                    if (e.isShiftDown()) {
                        // 在复杂运算文本框中添加乘方符号
                        complexTextField.setText(complexTextField.getText() + "^");
                    }
                }
            }
        });

        frame.setVisible(true);
    }

    /**
     * 创建简单运算按钮面板
     * 
     * @return 包含简单运算按钮的面板
     */
    private JPanel createSimpleButtons() {
        // 创建一个新的面板
        JPanel panel = new JPanel();
        // 设置面板的布局为5行4列的网格布局
        panel.setLayout(new GridLayout(5, 4));
        // 定义按钮标签数组
        String[] labels = { "7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "0", ".", "=", "+", "C", "(",
                ")" };
        // 遍历标签数组
        for (String label : labels) {
            // 创建一个新的按钮
            JButton button = new JButton(label);
            // 设置按钮的字体
            button.setFont(new Font("Arial", Font.BOLD, 20));
            // 如果标签是数字
            if (label.matches("[0-9]")) {
                // 设置按钮的背景颜色为白色
                button.setBackground(Color.WHITE);
            }
            // 如果标签是运算符
            else if (label.matches("[+\\-*/]")) {
                // 设置按钮的背景颜色为黄色
                button.setBackground(Color.YELLOW);
            }
            // 如果标签是等号
            else if (label.equals("=")) {
                // 设置按钮的背景颜色为绿色
                button.setBackground(Color.GREEN);
            }
            // 如果标签是清除按钮
            else if (label.equals("C")) {
                // 设置按钮的背景颜色为红色
                button.setBackground(Color.RED);
            }
            // 如果标签是括号
            else if (label.equals("(") || label.equals(")")) {
                // 设置按钮的背景颜色为青色
                button.setBackground(Color.CYAN);
            }
            // 为按钮添加动作监听器，监听按钮点击事件
            button.addActionListener(new SimpleButtonListener());
            // 将按钮添加到面板中
            panel.add(button);
        }
        // 返回创建好的按钮面板
        return panel;
    }

    /**
     * 创建复杂运算按钮面板
     * 
     * @return 包含复杂运算按钮的面板
     */
    private JPanel createComplexButtons() {
        // 创建一个新的面板
        JPanel panel = new JPanel();
        // 设置面板的布局为6行4列的网格布局
        panel.setLayout(new GridLayout(6, 4)); // 调整按钮布局为 6x4
        // 定义按钮标签数组
        String[] labels = { "sqrt", "^", "sin", "cos", "tan", "log", "ln", "(", ")", "/", "7", "8", "9",
                " ", "-", "4", "5", "6", "C", "*", "1", "2", "3", "=", "+", "0", ".", " "
        };
        for (String label : labels) {
            JButton button = new JButton(label);
            button.setFont(new Font("Arial", Font.BOLD, 20));

            // 根据按钮标签设置按钮背景颜色
            if (label.matches("[0-9]")) {
                button.setBackground(Color.WHITE);
            } else if (label.matches("[+\\-*/]")) {
                button.setBackground(Color.YELLOW);
            } else if (label.equals("=")) {
                button.setBackground(Color.GREEN);
            } else if (label.equals("C")) {
                button.setBackground(Color.RED);
            } else if (label.matches("sqrt|\\^|sin|cos|tan|log|ln")) {
                button.setBackground(Color.CYAN);
            } else if (label.equals("(") || label.equals(")")) {
                button.setBackground(Color.CYAN);
            }

            button.addActionListener(new ComplexButtonListener());
            panel.add(button);
        }
        return panel;
    }

    /**
     * 计算简单运算的结果
     */
    private void calculateSimpleResult() {
        // 获取简单运算文本框中的表达式
        String expression = simpleTextField.getText();
        try {
            // 计算表达式的结果
            double result = eval(expression);
            // 将tresult 结果显示在简单运算文本框中
            simpleTextField.setText(String.valueOf(result));
            // 将结果存储到记忆栈中
            memory.push(result);
        } catch (ArithmeticException ex) {
            // 如果发生算术异常，显示错误信息
            simpleTextField.setText("Error: Division by zero");
        } catch (Exception ex) {
            // 如果发生其他异常，显示错误信息
            simpleTextField.setText("Error: Invalid expression");
        }
    }

    /**
     * 计算复杂运算的结果
     */
    private void calculateComplexResult() {
        // 获取复杂运算文本框中的表达式
        String expression = complexTextField.getText();
        try {
            // 计算表达式的结果
            double result = eval(expression);
            // 将tresult 结果显示在复杂运算文本框中
            complexTextField.setText(String.valueOf(result));
            // 将结果存储到记忆栈中
            memory.push(result);
        } catch (ArithmeticException ex) {
            // 如果发生算术异常，显示错误信息
            complexTextField.setText("Error: Division by zero");
        } catch (Exception ex) {
            complexTextField.setText("Error: Invalid expression");
        }
    }

    // 记忆栈
    private void recallMemory() {
        try {
            if (!memory.isEmpty()) {
                double lastResult = memory.peek();
                Component currentPanel = mainPanel
                        .getComponent(mainPanel.getComponentZOrder(mainPanel.getComponent(0)));
                if (currentPanel == simplePanel) {
                    simpleTextField.setText(String.valueOf(lastResult));
                } else {
                    complexTextField.setText(String.valueOf(lastResult));
                }
            } else {
                JOptionPane.showMessageDialog(frame, "Memory is empty");
            }
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(frame, "Error recalling memory");
        }
    }

    // 清空记忆栈
    private void clearMemory() {
        try {
            memory.clear();
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(frame, "Error clearing memory");
        }
    }

    private class SimpleButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            String command = ((JButton) e.getSource()).getText();
            if (command.equals("=")) {
                // 调用 calculateSimpleResult 方法计算简单运算的结果
                calculateSimpleResult();
            } else if (command.equals("C")) {
                // 如果命令是 "C"，则清空简单运算文本框
                simpleTextField.setText("");
            } else {
                // 将命令添加到简单运算文本框中
                simpleTextField.setText(simpleTextField.getText() + command);
            }
        }
    }

    /**
     * 复杂按钮监听器类，处理复杂运算按钮的点击事件
     */
    private class ComplexButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            // 获取按钮上的命令文本
            String command = ((JButton) e.getSource()).getText();
            if (command.equals("=")) {
                // 如果命令是 "="，则调用 calculateComplexResult 方法计算复杂运算的结果
                calculateComplexResult();
            } else if (command.equals("C")) {
                // 如果命令是 "C"，则清空复杂运算文本框
                complexTextField.setText("");
            } else {
                // 将命令添加到复杂运算文本框中
                complexTextField.setText(complexTextField.getText() + command);
            }
        }
    }

    /**
     * 计算表达式的值
     * 
     * @param str 要计算的表达式字符串
     * @return 表达式的计算结果
     */
    public static double eval(final String str) {
        // 使用匿名内部类实现表达式解析和计算
        return new Object() {
            // 当前解析位置
            int pos = -1;
            // 当前字符
            int ch;

            /**
             * 读取下一个字符
             */
            void nextChar() {
                // 如果当前位置小于字符串长度，则读取下一个字符，否则设置为 -1
                ch = (++pos < str.length()) ? str.charAt(pos) : -1;
            }

            /**
             * 匹配并消耗指定字符
             * 
             * @param charToEat 要匹配的字符
             * @return 是否成功匹配并消耗
             */
            boolean eat(int charToEat) {
                // 跳过空格
                while (ch == ' ')
                    nextChar();
                // 如果当前字符与要匹配的字符相同，则读取下一个字符并返回 true
                if (ch == charToEat) {
                    nextChar();
                    return true;
                }
                return false;
            }

            // 开始解析表达式
            double parse() {
                nextChar();
                double x = parseExpression();
                // 解析完成后，如果还有未解析的字符，抛出异常
                if (pos < str.length())
                    throw new RuntimeException("Unexpected: " + (char) ch);
                return x;
            }

            // 解析数字，数字可以是直接的数字或被括号包围的表达式
            double parseNumber() {
                if (ch == '(') {
                    nextChar();
                    double x = parseExpression();
                    eat(')');
                    return x;
                }

                int startPos = pos;
                // 收集数字部分的字符，直到不是数字或小数点为止
                while ((ch >= '0' && ch <= '9') || ch == '.')
                    nextChar();
                // 将数字部分的字符转换为 double 类型
                return Double.parseDouble(str.substring(startPos, pos));
            }

            // 解析函数，包括 sin, cos, tan, sqrt, log, ln 等
            double parseFunction() {
                if (ch == 's') {
                    nextChar();
                    if (str.startsWith("in", pos)) {
                        pos += 2;
                        eat('(');
                        double x = parseExpression();
                        eat(')');
                        // 检查 sin 函数的参数范围
                        if (x < -360 || x > 360) {
                            throw new IllegalArgumentException("sin function argument out of range");
                        }
                        // 计算 sin 值，将角度转换为弧度
                        return Math.sin(Math.toRadians(x));
                    } else if (str.startsWith("qrt", pos)) {
                        pos += 3;
                        eat('(');
                        double x = parseExpression();
                        eat(')');
                        // 检查 sqrt 函数的参数范围，必须为非负
                        if (x < 0) {
                            throw new IllegalArgumentException("sqrt function argument must be non-negative");
                        }
                        // 计算平方根
                        return Math.sqrt(x);
                    } else {
                        throw new RuntimeException("Invalid function: sin or sqrt expected");
                    }
                } else if (ch == 'c') {
                    nextChar();
                    if (str.startsWith("os", pos)) {
                        pos += 2;
                        eat('(');
                        double x = parseExpression();
                        eat(')');
                        // 检查 cos 函数的参数范围
                        if (x < -360 || x > 360) {
                            throw new IllegalArgumentException("cos function argument out of range");
                        }
                        // 计算 cos 值，将角度转换为弧度
                        return Math.cos(Math.toRadians(x));
                    } else {
                        throw new RuntimeException("Invalid function: cos expected");
                    }
                } else if (ch == 't') {
                    nextChar();
                    if (str.startsWith("an", pos)) {
                        pos += 2;
                        eat('(');
                        double x = parseExpression();
                        eat(')');
                        // 检查 tan 函数的参数范围，排除特殊角度
                        if (x == 90 || x == 270) {
                            throw new IllegalArgumentException("tan function argument invalid");
                        }
                        // 计算 tan 值，将角度转换为弧度
                        return Math.tan(Math.toRadians(x));
                    } else {
                        throw new RuntimeException("Invalid function: tan expected");
                    }
                } else if (ch == 'l') {
                    nextChar();
                    if (str.startsWith("og", pos)) {
                        pos += 2;
                        eat('(');
                        double x = parseExpression();
                        eat(')');
                        // 检查 log 函数的参数范围，必须为正
                        if (x <= 0) {
                            throw new IllegalArgumentException("log function argument must be positive");
                        }
                        // 计算以 10 为底的对数
                        return Math.log10(x);
                    } else if (str.startsWith("n", pos)) {
                        pos += 1;
                        eat('(');
                        double x = parseExpression();
                        eat(')');
                        // 检查 ln 函数的参数范围，必须为正
                        if (x <= 0) {
                            throw new IllegalArgumentException("ln function argument must be positive");
                        }
                        // 计算自然对数
                        return Math.log(x);
                    } else {
                        throw new RuntimeException("Invalid function: log or ln expected");
                    }
                } else {
                    throw new RuntimeException("Unknown function");
                }
            }

            // 解析表达式，由项组成，项之间可以是加或减运算符
            double parseExpression() {
                double x = parseTerm();
                for (;;) {
                    if (eat('+'))
                        x += parseTerm();
                    else if (eat('-'))
                        x -= parseTerm();
                    else
                        return x;
                }
            }

            // 解析项，由因子组成，因子之间可以是乘、除或幂运算符
            double parseTerm() {
                double x = parseFactor();
                for (;;) {
                    if (eat('*'))
                        x *= parseFactor();
                    else if (eat('/'))
                        x /= parseFactor();
                    else if (eat('^'))
                        x = Math.pow(x, parseFactor());
                    else
                        return x;
                }
            }

            // 解析因子，因子可以是数字、带符号的数字、括号包围的表达式或函数
            double parseFactor() {
                if (eat('+'))
                    return parseFactor();
                if (eat('-'))
                    return -parseFactor();

                double x;
                // 记录当前位置作为起始位置
                int startPos = pos;
                // 如果当前字符是左括号，解析表达式并匹配右括号
                if (eat('(')) {
                    x = parseExpression();
                    eat(')');
                }
                // 如果当前字符是数字或小数点，解析数字
                else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
                    x = parseNumber();
                }
                // 如果当前字符是函数名的首字母，解析函数调用
                else if (ch == 's' || ch == 'c' || ch == 't' || ch == 'l') { // functions
                    x = parseFunction();
                }
                // 如果当前字符不符合任何预期，抛出异常
                else {
                    throw new RuntimeException("Unexpected: " + (char) ch);
                }

                // 返回解析结果
                return x;
            }
        }.parse();
    }

    /**
     * 主函数，用于启动计算器GUI
     * 
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        // 创建计算器GUI实例
        new calculatorGUI();
    }
}
